<!doctype html>
<meta charset="utf-8">
<title>Collision detection</title>

<body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/4.5.5/pixi.min.js"></script>
    <script>

        //Aliases
        let Application = PIXI.Application,
            Container = PIXI.Container,
            loader = PIXI.loader,
            resources = PIXI.loader.resources,
            Graphics = PIXI.Graphics,
            TextureCache = PIXI.utils.TextureCache,
            Sprite = PIXI.Sprite,
            Text = PIXI.Text,
            TextStyle = PIXI.TextStyle;

        //Create a Pixi Application
        let app = new Application({
            width: window.innerWidth,
            height: window.innerHeight,
            antialiasing: true,
            transparent: false,
            resolution: 1
        }
        );

        //Add the canvas that Pixi automatically created for you to the HTML document
        document.body.appendChild(app.view);

        loader
            .add("images/cat.png")
            .load(setup);

        //Define any variables that are used in more than one function
        let cat, box, message, state;

        function setup() {

            //Create the box
            box = new PIXI.Graphics();
            box.beginFill(0xCCFF99);
            box.drawRect(0, 0, 64, 64);
            box.endFill();
            box.x = 120;
            box.y = 96;
            app.stage.addChild(box);

            //Create the `cat` sprite 
            cat = new Sprite(resources["images/cat.png"].texture);
            cat.x = 16;
            cat.y = 96;
            cat.vx = 0;
            cat.vy = 0;
            app.stage.addChild(cat);

            //Capture the keyboard arrow keys
            let left = keyboard(37),
                up = keyboard(38),
                right = keyboard(39),
                down = keyboard(40);

            //Left arrow key `press` method
            left.press = function () {

                //Change the cat's velocity when the key is pressed
                cat.vx = -5;
                cat.vy = 0;
            };

            //Left arrow key `release` method
            left.release = function () {

                //If the left arrow has been released, and the right arrow isn't down,
                //and the cat isn't moving vertically:
                //Stop the cat
                if (!right.isDown && cat.vy === 0) {
                    cat.vx = 0;
                }
            };

            //Up
            up.press = function () {
                cat.vy = -5;
                cat.vx = 0;
            };
            up.release = function () {
                if (!down.isDown && cat.vx === 0) {
                    cat.vy = 0;
                }
            };

            //Right
            right.press = function () {
                cat.vx = 5;
                cat.vy = 0;
            };
            right.release = function () {
                if (!left.isDown && cat.vy === 0) {
                    cat.vx = 0;
                }
            };

            //Down
            down.press = function () {
                cat.vy = 5;
                cat.vx = 0;
            };
            down.release = function () {
                if (!up.isDown && cat.vx === 0) {
                    cat.vy = 0;
                }
            };

            //Create the text sprite
            let style = new TextStyle({
                fontFamily: "sans-serif",
                fontSize: 18,
                fill: "white",
            });
            message = new Text("No collision...", style);
            message.position.set(8, 8);
            app.stage.addChild(message);

            //Set the game state
            state = play;

            //Start the game loop 
            app.ticker.add(delta => gameLoop(delta));
        }


        function gameLoop(delta) {

            //Update the current game state:
            state(delta);
        }

        function play(delta) {

            //use the cat's velocity to make it move
            cat.x += cat.vx;
            cat.y += cat.vy;

            //check for a collision between the cat and the box
            if (hitTestRectangle(cat, box)) {

                //if there's a collision, change the message text
                //and tint the box red
                message.text = "hit!";
                box.tint = 0xff3300;
            } else {

                //if there's no collision, reset the message
                //text and the box's color
                message.text = "No collision...";
                box.tint = 0xccff99;
            }
        }

        //The `hitTestRectangle` function
        function hitTestRectangle(r1, r2) {

            //Define the variables we'll need to calculate
            let hit, combinedHalfWidths, combinedHalfHeights, vx, vy;

            //hit will determine whether there's a collision
            hit = false;

            //Find the center points of each sprite
            r1.centerX = r1.x + r1.width / 2;
            r1.centerY = r1.y + r1.height / 2;
            r2.centerX = r2.x + r2.width / 2;
            r2.centerY = r2.y + r2.height / 2;

            //Find the half-widths and half-heights of each sprite
            r1.halfWidth = r1.width / 2;
            r1.halfHeight = r1.height / 2;
            r2.halfWidth = r2.width / 2;
            r2.halfHeight = r2.height / 2;

            //Calculate the distance vector between the sprites
            vx = r1.centerX - r2.centerX;
            vy = r1.centerY - r2.centerY;

            //Figure out the combined half-widths and half-heights
            combinedHalfWidths = r1.halfWidth + r2.halfWidth;
            combinedHalfHeights = r1.halfHeight + r2.halfHeight;

            //Check for a collision on the x axis
            if (Math.abs(vx) < combinedHalfWidths) {

                //A collision might be occuring. Check for a collision on the y axis
                if (Math.abs(vy) < combinedHalfHeights) {

                    //There's definitely a collision happening
                    hit = true;
                } else {

                    //There's no collision on the y axis
                    hit = false;
                }
            } else {

                //There's no collision on the x axis
                hit = false;
            }

            //`hit` will be either `true` or `false`
            return hit;
        };


        //The `keyboard` helper function
        function keyboard(keyCode) {
            let key = {};
            key.code = keyCode;
            key.isDown = false;
            key.isUp = true;
            key.press = undefined;
            key.release = undefined;

            //The `downHandler`
            key.downHandler = function (event) {
                if (event.keyCode === key.code) {
                    if (key.isUp && key.press) key.press();
                    key.isDown = true;
                    key.isUp = false;
                }
                event.preventDefault();
            };

            //The `upHandler`
            key.upHandler = function (event) {
                if (event.keyCode === key.code) {
                    if (key.isDown && key.release) key.release();
                    key.isDown = false;
                    key.isUp = true;
                }
                event.preventDefault();
            };

            //Attach event listeners
            window.addEventListener(
                "keydown", key.downHandler.bind(key), false
            );
            window.addEventListener(
                "keyup", key.upHandler.bind(key), false
            );
            return key;
        }

    </script>
</body>